package net.linlan.stage.handler;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import net.linlan.annotation.RepeatSubmit;
import net.linlan.sys.web.RedisService;
import net.linlan.commons.core.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.Map;

/**
 * @author Linlan
 * CreateTime:5/3/20 4:53 PM
 *
 * @version 1.0
 * @since 1.0
 *
 */
@Configuration
@Component
public class RepeatSubmitInterceptor extends HandlerInterceptorAdapter {
    public final String REPEAT_PARAMS = "repeatParams";

    public final String REPEAT_TIME = "repeatTime";

    public final String SESSION_REPEAT_KEY = "repeatData";

    /**
     * 间隔时间，单位:秒 默认10秒
     *
     * 两次相同参数的请求，如果间隔时间大于该参数，系统不会认定为重复提交的数据
     */
    @Value("${platform.repeatSubmit.intervalTime:5}")
    private int intervalTime;

    @Autowired
    private RedisService redisService;

    public void setIntervalTime(int intervalTime)
    {
        this.intervalTime = intervalTime;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
    {
        if (handler instanceof HandlerMethod)
        {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
            if (annotation == null)
            {
                return true;
            }

            if(this.intervalTime<=0){
                return true;
            }

            if (this.isRepeatSubmit(request,request.getMethod()))
            {
                return false;
            }

            return true;
        }
        else
        {
            return super.preHandle(request, response, handler);
        }
    }

    /**
     * 验证是否重复提交由子类实现具体的防重复提交的规则
     *
     * @param request   请求
     * @param type      类型
     * @return          true/false
     */
    public boolean isRepeatSubmit(HttpServletRequest request, String type){
        // 本次参数及系统时间
        String nowParams;
        if("POST".equals(type)){
            try{
                nowParams = this.getBodyString(request);
                String encrypt = request.getHeader("encrypt");
                String token = request.getHeader("token");
                String url = request.getRequestURI();
                if(!"1".equals(encrypt)){
                    if(url.contains("file/upload") || url.contains("modifyPhoto")){
                        Part file = request.getPart("file");
                        String fileName = file.getSubmittedFileName();
                        JSONObject json= new JSONObject();
                        json.put("fileName",fileName);
                        nowParams=json.toJSONString();
                    }else {
                        if(StringUtils.isNotBlank(nowParams)){
                            JSONObject json= JSON.parseObject(nowParams);
                            if(json.containsKey("t")){
                                json.remove("t");
                            }
                            nowParams=json.toJSONString();
                        }
                    }
                }
//                Map<String, Object> nowDataMap = new HashMap<String, Object>();
//                nowDataMap.put(REPEAT_PARAMS, nowParams);
//                nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());

                // 请求地址（作为存放session的key值）
                String oldParams = redisService.get(token+url);
                if(oldParams != null){
                    if(oldParams.equals(nowParams)){
                        return true;
                    }
                }else{
                    redisService.set(token+url, nowParams,intervalTime);
                    //session.setAttribute(SESSION_REPEAT_KEY, sessionMap);
                    return false;
                }
//                if (sessionObj != null){
//                    JSONObject sessionMap = JSONObject.parseObject(sessionObj);
//                    if (sessionMap.containsKey(url)){
//                        JSONObject preDataMap = sessionMap.getJSONObject(url);
//                        if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap)){
//                            return true;
//                        }
//                    }
//                }
//                    Map<String, Object> sessionMap = new HashMap<String, Object>();
//                    sessionMap.put(url, nowDataMap);


            }catch (Exception ex){
                return false;
            }
        }else if("GET".equals(type)){
            nowParams=JSONObject.toJSONString(request.getParameterMap());
        }else{
            return false;
        }
        return false;
    }

    public  String getBodyString(HttpServletRequest request) throws IOException {
        StringBuilder sb = new StringBuilder();
        InputStream inputStream = null;
        BufferedReader reader = null;
        try {
            inputStream = request.getInputStream();
            reader = new BufferedReader(
                    new InputStreamReader(inputStream, Charset.forName("UTF-8")));

            char[] bodyCharBuffer = new char[1024];
            int len = 0;
            while ((len = reader.read(bodyCharBuffer)) != -1) {
                sb.append(new String(bodyCharBuffer, 0, len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();
    }

    /**
     * 判断参数是否相同
     */
    private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap)
    {
        String nowParams = (String) nowMap.get(REPEAT_PARAMS);
        String preParams = (String) preMap.get(REPEAT_PARAMS);
        return nowParams.equals(preParams);
    }

    /**
     * 判断两次间隔时间
     */
    private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap)
    {
        long time1 = (Long) nowMap.get(REPEAT_TIME);
        long time2 = (Long) preMap.get(REPEAT_TIME);
        if ((time1 - time2) < (this.intervalTime * 1000))
        {
            return true;
        }
        return false;
    }
}
